/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.suli.check.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.entity.Result;
import me.zhengjie.suli.check.domain.CheckRecord;
import me.zhengjie.suli.inventory.domain.Inventory;
import me.zhengjie.suli.inventory.repository.InventoryRepository;
import me.zhengjie.suli.wcs.domain.AgvTasks;
import me.zhengjie.suli.wcs.repository.AgvTasksRepository;
import me.zhengjie.util.CommonUtil;
import me.zhengjie.util.UuidUtil;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.suli.check.repository.CheckRecordRepository;
import me.zhengjie.suli.check.service.CheckRecordService;
import me.zhengjie.suli.check.service.dto.CheckRecordDto;
import me.zhengjie.suli.check.service.dto.CheckRecordQueryCriteria;
import me.zhengjie.suli.check.service.mapstruct.CheckRecordMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Allen Gao
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-04-11
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class CheckRecordServiceImpl implements CheckRecordService {

    private final CheckRecordRepository checkRecordRepository;
    private final CheckRecordMapper checkRecordMapper;
    private final CommonUtil commonUtil;
    private final InventoryRepository inventoryRepository;
    private final AgvTasksRepository agvTasksRepository;

    @Value("${agv.port}")
    private String agvPort;

    @Value("${agv.ip}")
    private String agvIp;

    @Override
    public Map<String, Object> queryAll(CheckRecordQueryCriteria criteria, Pageable pageable) {
        Page<CheckRecord> page = checkRecordRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(checkRecordMapper::toDto));
    }

    @Override
    public List<CheckRecordDto> queryAll(CheckRecordQueryCriteria criteria) {
        return checkRecordMapper.toDto(checkRecordRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public CheckRecordDto findById(String id) {
        CheckRecord checkRecord = checkRecordRepository.findById(id).orElseGet(CheckRecord::new);
        ValidationUtil.isNull(checkRecord.getId(), "CheckRecord", "id", id);
        return checkRecordMapper.toDto(checkRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckRecordDto create(CheckRecord resources) {
        resources.setId(IdUtil.simpleUUID());
        return checkRecordMapper.toDto(checkRecordRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(CheckRecord resources) {
        CheckRecord checkRecord = checkRecordRepository.findById(resources.getId()).orElseGet(CheckRecord::new);
        ValidationUtil.isNull(checkRecord.getId(), "CheckRecord", "id", resources.getId());
        checkRecord.copy(resources);
        checkRecordRepository.save(checkRecord);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            checkRecordRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<CheckRecordDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (CheckRecordDto checkRecord : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("抽检编码", checkRecord.getCheckCode());
            map.put("物料编码", checkRecord.getMaterialCode());
            map.put("物料名称", checkRecord.getMaterialName());
            map.put("单位", checkRecord.getUnit());
            map.put("库存数量", checkRecord.getPlanQty());
            map.put("抽检数量", checkRecord.getCheckQty());
            map.put("载具", checkRecord.getTrayCode());
            map.put("库位", checkRecord.getLocationCode());
            map.put("批次号", checkRecord.getLotCode());
            map.put("箱号", checkRecord.getPkList());
            map.put("等级", checkRecord.getGrade());
            map.put("是否VMI", checkRecord.getVmiCode());
            map.put("供应商代码", checkRecord.getSuNo());
            map.put("项目号", checkRecord.getChSeq());
            map.put("工厂", checkRecord.getWaNo());
            map.put("源单号", checkRecord.getSourceCode());
            map.put("创建用户", checkRecord.getCreateBy());
            map.put("修改用户", checkRecord.getUpdateBy());
            map.put("创建日期", checkRecord.getCreateTime());
            map.put("修改日期", checkRecord.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 作废。 Allen Gao 2024-04-13， 抽检出库再抽检页面中完成
     */
    @Override
    public String addOutBoundCheck(String param) {
        Inventory inventory = inventoryRepository.findByTrayCodeTop(param);
        JSONObject agvTask = new JSONObject();
        agvTask.put("taskType", "tote_outbound");
//        agvTask.put("groupPriority", 1);
        agvTask.put("taskGroupCode", UuidUtil.genCode());
        JSONObject task = new JSONObject();
        task.put("taskCode", UuidUtil.genCode());
        task.put("taskPriority", 100);
        List<JSONObject> tasks = new ArrayList<>();
        JSONObject taskDescribe = new JSONObject();
        taskDescribe.put("containerCode", inventory.getTrayCode());
        taskDescribe.put("storageTag", "");
        taskDescribe.put("fromLocationCode", "");
        List<String> toLocationCode = new ArrayList<>();
        toLocationCode.add("CY01");
        taskDescribe.put("toStationCode", toLocationCode);
        task.put("taskDescribe", taskDescribe);
        tasks.add(task);
        AgvTasks agvTasks = new AgvTasks();
        agvTasks.setId(UuidUtil.genCode());
        agvTasks.setStatus(1);
        agvTasks.setTaskType("抽检");
        agvTasks.setCreateTime(new Timestamp(new Date().getTime()));
        agvTasks.setTaskGroupCode(agvTask.getString("taskGroupCode"));
        agvTasks.setBillNumber(task.getString("taskCode"));
        agvTasks.setCreateBy(SecurityUtils.getCurrentUsername());
        String s = commonUtil.httpPost("http://" + agvIp + ":" + agvPort + "/task/create", agvTask);
        Result result = JSON.parseObject(s, Result.class);
        log.info("抽检发货发送任务收到agv反馈" + result);
        if (result.getCode() != 0) {
            log.info("抽检发货发送任务时异常，原因：" + result);
            return "箱号为：" + inventory.getBoxNumber() + "的订单agv响应异常";
        } else {
            inventory.setIsHold(1);
            inventoryRepository.save(inventory);
            agvTasksRepository.save(agvTasks);
            return "success";
        }
    }

    /**
     * 抽检回库 Allen Gao 2024-04-14 修改业务
     */
    @Override
    public String pointCheckReturn(String param) {
        JSONObject paramObject = JSON.parseObject(param);
        String boxNumber = paramObject.getString("boxNumber");
//        BigDecimal actQty = paramObject.getBigDecimal("actQty");
        /** 修改抽检记录 */
        CheckRecord checkRecord = checkRecordRepository.getCheckRecordByBoxNumberAndStatus(boxNumber, 1);
//        checkRecord.setCheckQty(actQty);
//        checkRecord.setDiffQty(actQty.subtract(checkRecord.getPlanQty()));
//        checkRecordRepository.save(checkRecord);

        Inventory inventory = inventoryRepository.findByBoxNumber(boxNumber);
        inventory.setWarehouseLocation(checkRecord.getLocationCode());
        inventory.setLocationCode(checkRecord.getLocationCode());
        inventory.setTrayCode(checkRecord.getTrayCode());
        inventoryRepository.save(inventory);
        JSONObject agvTask = new JSONObject();
        agvTask.put("taskType", "putaway");
//        agvTask.put("groupPriority", 1);
        agvTask.put("taskGroupCode", UuidUtil.genCode());
        JSONObject task = new JSONObject();
        task.put("taskCode", UuidUtil.genCode());
        task.put("taskPriority", 100);
        List<JSONObject> tasks = new ArrayList<>();
        JSONObject taskDescribe = new JSONObject();
        taskDescribe.put("containerCode", checkRecord.getTrayCode());
        taskDescribe.put("storageTag", "");
        taskDescribe.put("toLocationCode", checkRecord.getLocationCode());
        task.put("taskDescribe", taskDescribe);
        tasks.add(task);
        AgvTasks agvTasks = new AgvTasks();
        agvTasks.setId(UuidUtil.genCode());
        agvTasks.setStatus(1);
        agvTasks.setTaskType("抽检回库");
        agvTasks.setCreateTime(new Timestamp(new Date().getTime()));
        agvTasks.setTaskGroupCode(agvTask.getString("taskGroupCode"));
        agvTasks.setBillNumber(task.getString("taskCode"));
        agvTasks.setCreateBy(SecurityUtils.getCurrentUsername());
        agvTask.put("tasks",tasks);
        String s = commonUtil.httpPost("http://" + agvIp + ":" + agvPort + "/task/create", agvTask);
        Result result = JSON.parseObject(s, Result.class);
        log.info("抽检回库发送任务收到agv反馈" + result);
        if (result.getCode() != 0) {
            log.info("抽检回库发送任务时异常，原因：" + result);
            return "箱号为：" + inventory.getBoxNumber() + "的抽检回库agv响应异常";
        } else {
            JSONObject jsonObject2 = new JSONObject();
            jsonObject2.put("slotCode", "1-5");
            jsonObject2.put("containerCode", inventory.getTrayCode());
            jsonObject2.put("direction", "100");
            String sp = commonUtil.httpPost("http://" + agvIp + ":" + agvPort + "/conveyor/moveContainer", jsonObject2.toJSONString());
            agvTasksRepository.save(agvTasks);
            return "success";
        }
    }
}